package com.along.utility.common.utils;

import com.github.pagehelper.Page;
import com.google.common.collect.Lists;
import org.springframework.cglib.beans.BeanCopier;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author jingjiwu
 * @date 2021-01-05 15:27:37
 */
public class ListCopier {
	private static final ConcurrentHashMap<String, BeanCopier> mapCaches = new ConcurrentHashMap<>();

	private ListCopier() {
	}

	// 使用 ConcurrentHashMap 保证线程安全

	/**
	 * 对象列表复制
	 * @param sources 源对象列表
	 * @param targetClass 目标类
	 * @param <T> 源类型
	 * @param <E> 目标类型
	 * @return 复制后的列表
	 * @throws IllegalArgumentException 如果参数不合法
	 */
	public static <T, E> List<E> copy(List<T> sources, Class<E> targetClass) {
		// 参数校验
		if (sources == null) {
			return Lists.newArrayList();
		}
		if (targetClass == null) {
			throw new IllegalArgumentException("Target class cannot be null");
		}
		if (sources.isEmpty()) {
			return Lists.newArrayList();
		}

		// 获取或创建 BeanCopier
		String baseKey = generateKey(sources.get(0).getClass(), targetClass);
		BeanCopier copier = mapCaches.computeIfAbsent(baseKey, key ->
				BeanCopier.create(sources.get(0).getClass(), targetClass, false)
		);

		// 执行复制
		List<E> result = Lists.newArrayListWithCapacity(sources.size());
		for (T src : sources) {
			if (src == null) {
				continue; // 跳过 null 元素
			}

			try {
				E instance = targetClass.getDeclaredConstructor().newInstance();
				copier.copy(src, instance, null);
				result.add(instance);
			} catch (Exception e) {
				throw new RuntimeException(
						String.format("Failed to copy object from %s to %s",
								src.getClass().getSimpleName(),
								targetClass.getSimpleName()),
						e);
			}
		}
		return result;
	}

	/**
	 *
	 * @param entity
	 * @param dto
	 * @return
	 * @author pingguanfei
	 * @date 2021-01-13 12:36:45
	 *
	 */
	/**
	 * 分页对象复制
	 * @param sourcePage 源分页对象
	 * @param targetClass 目标类
	 * @param <T> 源类型
	 * @param <E> 目标类型
	 * @return 复制后的分页对象
	 * @throws IllegalArgumentException 如果参数不合法
	 */
	public static <T, E> Page<E> pageCopy(Page<T> sourcePage, Class<E> targetClass) {
		Objects.requireNonNull(sourcePage, "Source page cannot be null");
		Objects.requireNonNull(targetClass, "Target class cannot be null");

		List<E> dtos = copy(sourcePage.getResult(), targetClass);
		Page<E> pageDTO = new Page<>();
		pageDTO.setTotal(sourcePage.getTotal());
		pageDTO.addAll(dtos);
		return pageDTO;
	}


	private static String generateKey(Class<?> src, Class<?> tag) {
		return String.format("%s%s", src.toString(), tag.toString());
	}
}
